//
//	UDP Server :
//

#include <stdio.h>
#include <conio.h>
#include <exception>
#include "winsock2.h"

using namespace std;

#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "Advapi32.lib")

typedef unsigned int uint;
#define LOGF			printf
#define LOG_VALUE(val)	log_value(#val, val)
#define LOG_INIT(s)		printf("INIT : %s\r\n", s)
#define LOG_SHUTDOWN(s)	printf("SHUTDOWN : %s\r\n", s)

inline void log_value(const char *name, int   val)			{ LOGF("%-30s = %d\r\n", name, val); }
inline void log_value(const char *name, float val)			{ LOGF("%-30s = %f\r\n", name, val); }
inline void log_value(const char *name, const char *val)	{ LOGF("%-30s = %s\r\n", name, val); }


#include "net_helper.h"
#include "net_shared.h"


class EServer {
	public:
					EServer		( uint port );
					~EServer	( void );
		void		Frame		( void );
	protected:
		uint		port_listen;
		SOCKET		sock_listen;
		sockaddr_in	addr_listen;
	};


EServer::EServer(uint port)
{
	port_listen	=	port;
	int r = 0;
	unsigned long enable = 1;
	int one = 1;
	

	WSADATA		wsaData;
	WSAStartup(MAKEWORD(2,2), &wsaData);
	
	sock_listen	=	socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

	addr_listen.sin_family		= AF_INET;
	addr_listen.sin_port		= htons(port_listen);
	addr_listen.sin_addr.s_addr = htonl(INADDR_ANY);

	//	TODO : make function for socket creation :
	CHECK_WSA( bind(sock_listen, (SOCKADDR*)&addr_listen, sizeof(addr_listen)) );
	CHECK_WSA( ioctlsocket( sock_listen, FIONBIO, &enable ) );
	CHECK_WSA( setsockopt( sock_listen, SOL_SOCKET, SO_BROADCAST, (char*)&one, sizeof(one)) );
}


void EServer::Frame( void )
{
	ENetPacket_s packet;
	sockaddr_in	 addr_sender;
	int			 addr_sender_size = sizeof(addr_sender);
	packet.Fill(0);
	
	if ( wait( recvfrom( sock_listen, (char*)&packet, MAX_PACKET_SIZE, 0, (sockaddr*)&addr_sender, &addr_sender_size) ) ) {
		LOGF("received packet:\r\n");
		LOGF("  port : %d\r\n", addr_sender.sin_port);
		LOGF("  addr : %s\r\n", inet_ntoa(addr_sender.sin_addr));
		LOGF("  data : %s\r\n", packet.data);
	}
}


EServer::~EServer(void)
{
	WSACleanup();
}



void main() {
	
	try {
		EServer	sv(12345);
		
		while (1) {
			Sleep(5);
			sv.Frame();
		}
	} catch (exception &e) {
		LOGF("ERROR : %s\r\n", e.what());
		getch();
	}

#if 0  
  WSADATA wsaData;
  SOCKET SendSocket;
  sockaddr_in RecvAddr;
  int Port = 27015;
  char SendBuf[1024];
  int BufLen = 1024;

  //---------------------------------------------
  // Initialize Winsock
  WSAStartup(MAKEWORD(2,2), &wsaData);

  //---------------------------------------------
  // Create a socket for sending data
  SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

  //---------------------------------------------
  // Set up the RecvAddr structure with the IP address of
  // the receiver (in this example case "123.456.789.1")
  // and the specified port number.
  RecvAddr.sin_family = AF_INET;
  RecvAddr.sin_port = htons(Port);
  RecvAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

  //---------------------------------------------
  // Send a datagram to the receiver
  printf("Sending a datagram to the receiver...\n");
  sendto(SendSocket, 
    SendBuf, 
    BufLen, 
    0, 
    (SOCKADDR *) &RecvAddr, 
    sizeof(RecvAddr));

  //---------------------------------------------
  // When the application is finished sending, close the socket.
  printf("Finished sending. Closing socket.\n");
  closesocket(SendSocket);

  //---------------------------------------------
  // Clean up and quit.
  printf("Exiting.\n");
  WSACleanup();
  return;
#endif  
}
